function Prerequisites()
{
	this.targets = new Array();
	this.compress = false;
	this.dirty = false;

	this.isDirty = PrerequisitesIsDirty;

	// Remove all or some of the prerequisites for a specified target.
	this.removePrerequisites = PrerequisitesRemove;
	// Performs actual object deletion for removePrerequisites().
	this.deleteAllPrerequisites = PrerequisitesDeleteAll;
	// Returns an array of Page and/or Topic objects
	// for the specified target.
	this.getPrerequisites = PrerequisitesGet;
	// Returns true if the specified prerequisite exists
	// for the specified target.
	this.prerequisiteExists = PrerequisitesPrerequisiteExits;
	// Adds the specified prerequisites to the
	// specified target.
	this.addPrerequisites = PrerequisitesAddPrerequisites;
	// Returns true if the specified target exists.
	this.targetExists = PrerequisitesTargetExists;
	// Adds the specified target.
	this.addTarget = PrerequisitesAddTarget;
	// Returns a reference to the specified target.
	this.getTarget = PrerequisitesGetTarget;
	// Outputs data to a string.
	this.dump = PrerequisitesDump;
	// Inputs data from a string.
	this.load = PrerequisitesLoad;
	// Clears all data.
	this.clear = PrerequisitesClear;
}

function PrerequisitesAddTarget(obj)
{
	if (obj.type == "Page")
	{
		this.targets[this.targets.length] = new Page(obj.section, obj.topic, obj.subtopic, obj.page);
	}
	else if (obj.type == "Topic")
	{
		this.targets[this.targets.length] = new Topic(obj.section, obj.topic, obj.subtopic);
	}
}

function PrerequisitesTargetExists(obj)
{
	if (this.getTarget(obj) == null)
	{
		return false;
	}
	else
	{
		return true;
	}
}

function PrerequisitesGetTarget(obj)
{
	for (var i=0;i<this.targets.length;i++)
	{
		if (this.targets[i].compare(obj))
		{
			return this.targets[i];
		}
	}
	return null;
}

function PrerequisitesAddPrerequisites(obj)
{
	var target = null;
	var next = null;
	var prev = null;
	
	if (!this.targetExists(obj))
	{
		this.addTarget(obj);
	}
	target = this.getTarget(obj);
	
	// Find the last prereq in the chain.
	prev = target;
	next = target.next;
	while (next != null)
	{
		prev = next;
		next = next.next;
	}
	// Now add the prerequisites to the chain.
	next = prev;
	for (var i=1;i<PrerequisitesAddPrerequisites.arguments.length;i++)
	{
		if (!this.prerequisiteExists(target, PrerequisitesAddPrerequisites.arguments[i]))
		{
			this.dirty = true;
			if (PrerequisitesAddPrerequisites.arguments[i].type == "Page")
			{
				next.next = new Page(PrerequisitesAddPrerequisites.arguments[i].section, PrerequisitesAddPrerequisites.arguments[i].topic, PrerequisitesAddPrerequisites.arguments[i].subtopic, PrerequisitesAddPrerequisites.arguments[i].page);
			}
			else if (PrerequisitesAddPrerequisites.arguments[i].type == "Topic")
			{
				next.next = new Topic(PrerequisitesAddPrerequisites.arguments[i].section, PrerequisitesAddPrerequisites.arguments[i].topic, PrerequisitesAddPrerequisites.arguments[i].subtopic);
			}
			next = next.next;
		}
	}
}

function PrerequisitesPrerequisiteExits(objTarget, objPrereq)
{
	if (this.targetExists(objTarget))
	{
		var next = this.getTarget(objTarget);
		next = next.next;
		while (next != null)
		{
			if (next.compare(objPrereq))
			{
				return true;
			}
			next = next.next;
		}
	}
	return false;
}

function PrerequisitesGet(obj)
{
	var arr = new Array();
	if (this.targetExists(obj))
	{
		var next = this.getTarget(obj);
		next = next.next;
		while (next != null)
		{
			if (next.type == "Page")
			{
				arr[arr.length] = new Page(next.section, next.topic, next.subtopic, next.page);
			}
			else if (next.type == "Topic")
			{
				arr[arr.length] = new Topic(next.section, next.topic, next.subtopic);
			}
			next = next.next;
		}
	}
	return arr;
}
 
function PrerequisitesClear()
{
	for (var i=0;i<this.targets.length;i++)
	{
		this.removePrerequisites(this.targets[i]);
		this.targets.length = 0;
	}
	this.dirty = false;
}
 
// If only the target is specified, then all of its
// prerequisites will be removed.
function PrerequisitesRemove(obj)
{
	if (PrerequisitesRemove.arguments.length <= 1) // Delete them all.
	{
		if (this.targetExists(obj))
		{
			this.deleteAllPrerequisites(this.getTarget(obj));
			this.dirty = true;
		}
	}
	else
	{
		// Delete those from the list provided.
		var target = null;
		target = this.getTarget(obj);
		
		if (target != null)
		{
			// For each object in the argument list, find it
			// in its target's list and remove it.
			for (var i=1;i<PrerequisitesRemove.arguments.length;i++)
			{
				var next = target.next;
				var prev = target;
				while (next != null)
				{
					if (next.compare(PrerequisitesRemove.arguments[i]))
					{
						// Found it.  Now remove it.
						prev.next = next.next;
						delete next;
						this.dirty = true;
						break; // Break out of while loop.
					}
					prev = next;
					next = next.next;
				}
			}
		}
	}
}

function PrerequisitesDeleteAll(obj)
{
	if (obj.next != null)
	{
		this.deleteAllPrerequisites(obj.next);
		delete obj.next;
	}
}

function PrerequisitesDump()
{
	var temp = "";
	var foundFirstTarget = false;
	for (var i=0;i<this.targets.length;i++)
	{
		if (this.targets[i].next != null)
		{
			// Add an entry into the temp string.
			
			if (foundFirstTarget)
			{
				temp += "-";
			}
			else
			{
				foundFirstTarget = true;
			}
			
			// Add the entry for the target first.
			if (this.targets[i].type == "Page")
			{
				temp += "P" + this.targets[i].section + "T" + this.targets[i].topic + "U" + this.targets[i].subtopic + "R" + this.targets[i].page;
			}
			else if (this.targets[i].type == "Topic")
			{
				temp += "T" + this.targets[i].section + "T" + this.targets[i].topic + "U" + this.targets[i].subtopic;
			}
			
			// Add all of the prereqs to the temp string next.
			var next = this.targets[i].next;
			while (next != null)
			{
				if (next.type == "Page")
				{
					temp += "+P" + next.section + "T" + next.topic + "U" + next.subtopic + "R" + next.page;
				}
				else if (next.type == "Topic")
				{
					temp += "+T" + next.section + "T" + next.topic + "U" + next.subtopic;
				}
				next = next.next;
			}
		}
	}
	this.dirty = false;
 	if (this.compress)
	{
		return compressUnicodeString(temp);
	}
	else
	{
		return temp;
	}
}

function PrerequisitesLoad(dataString)
{
	if (this.compress)
	{
		dataString = uncompressUnicodeString(dataString);
	}
	
	this.clear();

	if (dataString == "") return;
	var setArray = dataString.split("-");

	for (var i=0;i<setArray.length;i++)
	{	
		var target = null;
		var prereq = null;
		var index = null;
		if (setArray[i].charAt(0) == "P")
		{
			setArray[i] = setArray[i].slice(1,setArray[i].length);
			target = new Page(0,0,0,0);
			
			index = setArray[i].indexOf("T");
			target.section = parseInt(setArray[i].slice(0,index));
			setArray[i] = setArray[i].slice(index+1,setArray[i].length);
			
			index = setArray[i].indexOf("U");
			target.topic = parseInt(setArray[i].slice(0,index));
			setArray[i] = setArray[i].slice(index+1,setArray[i].length);

			index = setArray[i].indexOf("R");
			target.subtopic = parseInt(setArray[i].slice(0,index));
			setArray[i] = setArray[i].slice(index+1,setArray[i].length);

			index = setArray[i].indexOf("+");
			target.page = parseInt(setArray[i].slice(0,index));
			setArray[i] = setArray[i].slice(index+1,setArray[i].length);
		}
		else if (setArray[i].charAt(0) == "T")
		{
			setArray[i] = setArray[i].slice(1,setArray[i].length);
			target = new Topic(0,0,0);
			
			index = setArray[i].indexOf("T");
			target.section = parseInt(setArray[i].slice(0,index));
			setArray[i] = setArray[i].slice(index+1,setArray[i].length);
			
			index = setArray[i].indexOf("U");
			target.topic = parseInt(setArray[i].slice(0,index));
			setArray[i] = setArray[i].slice(index+1,setArray[i].length);

			index = setArray[i].indexOf("+");
			target.subtopic = parseInt(setArray[i].slice(0,index));
			setArray[i] = setArray[i].slice(index+1,setArray[i].length);
		}
		
		var prereqArray = setArray[i].split("+");
		for (var t=0;t<prereqArray.length;t++)
		{
			if (prereqArray[t].charAt(0) == "P")
			{
				prereqArray[t] = prereqArray[t].slice(1,prereqArray[t].length);
				prereq = new Page(0,0,0,0);
				
				index = prereqArray[t].indexOf("T");
				prereq.section = parseInt(prereqArray[t].slice(0,index));
				prereqArray[t] = prereqArray[t].slice(index+1,prereqArray[t].length);

				index = prereqArray[t].indexOf("U");
				prereq.topic = parseInt(prereqArray[t].slice(0,index));
				prereqArray[t] = prereqArray[t].slice(index+1,prereqArray[t].length);

				index = prereqArray[t].indexOf("R");
				prereq.subtopic = parseInt(prereqArray[t].slice(0,index));
				prereqArray[t] = prereqArray[t].slice(index+1,prereqArray[t].length);

				prereq.page = parseInt(prereqArray[t]);
			}
			else if (prereqArray[t].charAt(0) == "T")
			{
				prereqArray[t] = prereqArray[t].slice(1,prereqArray[t].length);
				prereq = new Topic(0,0,0);
				
				index = prereqArray[t].indexOf("T");
				prereq.section = parseInt(prereqArray[t].slice(0,index));
				prereqArray[t] = prereqArray[t].slice(index+1,prereqArray[t].length);
				
				index = prereqArray[t].indexOf("U");
				prereq.topic = parseInt(prereqArray[t].slice(0,index));
				prereqArray[t] = prereqArray[t].slice(index+1,prereqArray[t].length);
	
				prereq.subtopic = parseInt(prereqArray[t]);
			}
			this.addPrerequisites(target, prereq);
		}
	}
}

function PrerequisitesIsDirty()
{
	return this.dirty;
}
